﻿

namespace WPF.TestEditor.Common
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using AppProperties = WPF.TestEditor.Properties;
    using ICSharpCode.AvalonEdit.Highlighting;
    using ICSharpCode.AvalonEdit.CodeCompletion;

    using ICSharpCode.AvalonEdit.Editing;
    using EasyStep.Business.Interfaces;
    using EasyStep.Attributes;
    using ICSharpCode.AvalonEdit;
    using EasyStep.Data.Entities;
    using ICSharpCode.AvalonEdit.Rendering;
    using ICSharpCode.AvalonEdit.Document;
    using System.Text.RegularExpressions;
    using WPF.TestEditor.Controls;


    public class DynamicACCollection
    {
            public TextEditorComletitionData[] actions;
            public List<TestAction> normalizedActions;
            public TextEditorComletitionData[] constantsTests;
            private ITestDataContext DataContext;
            public Regex leftPartRx;
            public Regex leftPartParentRx;

            public DynamicACCollection(ITestDataContext dContext)
            {
                DataContext = dContext;
                if (DataContext == null) return;
                var allActions = dContext.ActionManager.GetAll();
                normalizedActions = allActions.Where(ai => !ai.IsAbstract).ToList();
                actions = normalizedActions.Select(a =>
                    a.Parent == null
                    ? new TextEditorComletitionData(string.Format("{0} =", a.Name), a.Name, 0, ActionBaseIcon)
                    : new TextEditorComletitionData(string.Format("{0}, {1} =", a.Parent.Name, a.Name), string.Concat(a.Parent.Name, ", ", a.Name), 0, ActionIcon)
                ).ToArray();

                constantsTests = dContext.ConstantsManager.GetAll().OrderBy(c=>c.Name).Select(c => new TextEditorComletitionData("c:" + c.Name, c.Value, 0, ConstIcon))
                    .Union(dContext.TestInfoManager.GetProjectTests().OrderBy(p=>p.Name).Select(t => new TextEditorComletitionData(t.Name, t.Name, 0, TestIcon)))
                    .ToArray();
                leftPartRx = new Regex("^\\s*[^=]+\\s*(?:=|$)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
                leftPartParentRx = new Regex("^\\s*[^,]+\\s*,\\s*[^=]+\\s*=", RegexOptions.IgnoreCase | RegexOptions.Compiled);

            }

            private ImageSource GetImageSource(string filename)
            {
                filename = System.IO.Path.Combine(AppProperties.Settings.Default.ResourceFolder, filename);
                if (!System.IO.File.Exists(filename))
                {
                    DataContext.Log.Error("Can't find image resource:" + filename);
                    return null;
                }
                ImageSource result = null;
                try
                {
                    result = new BitmapImage(new Uri(filename, UriKind.Absolute));
                }
                catch (Exception ex)
                {
                    DataContext.Log.Error("Can't load image resource:" + filename, ex);
                }
                return result;
            }
            public bool CheckRegex(string pattern, string text, Action<Match> onMatch)
            {
                bool result = false;
                var reg = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);

                for (var regMatch = reg.Match(text); regMatch.Success; regMatch = regMatch.NextMatch())
                {
                    if (regMatch.Length < 1) continue;
                    onMatch(regMatch);
                    result = true;
                }
                return result;
            }
            public bool CheckRegex(Regex pattern, string text, Action<Match> onMatch)
            {
                bool result = false;
                for (var regMatch = pattern.Match(text); regMatch.Success; regMatch = regMatch.NextMatch())
                {
                    if (regMatch.Length < 1) continue;
                    result = true;
                    onMatch(regMatch);
                }
                return result;
            }
            public T BuildList<T>(TextArea area, Func<T> onDataExist)
                where T : WPF.TestEditor.Controls.AvalonTextEditor.CompletionWindow
            {
                var o = area.Caret.Offset;

                var ln = area.Document.GetLineByNumber(area.Caret.Line);
                var text = area.Document.GetText(ln.Offset, o - ln.Offset);
                TextEditorComletitionData[] dataToShow = null;
                var offset = -1;
                var leftRightDeliminator = -1;
                if (!CheckRegex(leftPartParentRx, text, (m) =>
                {
                    leftRightDeliminator = m.Index + m.Length;
                    offset = leftRightDeliminator;
                })
                ) CheckRegex(leftPartRx, text, (m) => offset = m.Index + m.Length);

                if (leftRightDeliminator > 0)
                {//after "=" symbol
                    offset = leftRightDeliminator;
                    var right = text.Substring(leftRightDeliminator);
                    var processed = false;
                    while (!processed)
                    {//at least 1 times we could skip text (where locator already filled in with correct data structure
                        if (!CheckRegex("^\\s*([\"'])", right, (m) =>
                        {
                            var g = m.Groups[1];
                            if (!CheckRegex(string.Format("^\\s*{0}\\s*([^{0}]*){0}\\s*,", g.Value), right, (m1) =>
                            {
                                right = right.Substring(m1.Length);
                                offset += m1.Length;
                            })
                            )
                            {
                                processed = true;
                                offset += g.Index + g.Length;
                                right = right.Substring(g.Index + g.Length);
                            }
                        }))
                            if (!CheckRegex("^\\s*[^,]*,", right, (m1) =>
                            {
                                right = right.Substring(m1.Length);
                                offset += m1.Length;
                            }))
                                processed = true;
                    }
                    CheckRegex("^\\s*", right, (m) => offset += m.Length);
                    dataToShow = constantsTests;
                }
                else
                {
                    offset = text.IndexOf(",");
                    if (offset < 0)
                    {
                        dataToShow = actions;
                        offset = 0;
                    }
                    else
                    {
                        var pname = text.Substring(0, offset).Trim();
                        var r = normalizedActions.Where(a => a.Parent != null && a.Parent.Name.Equals(pname, StringComparison.OrdinalIgnoreCase))
                            .Select(a => new TextEditorComletitionData(", " + a.Name + " =", a.Name, 0, ActionIcon)
                        ).ToArray();
                        if (r.Length < 1) dataToShow = null;
                        else dataToShow = r;
                    };
                }
                if (dataToShow == null || dataToShow.Length == 0) return default(T);
                var cwmanager = onDataExist();
                cwmanager.CompletionList.CompletionData = dataToShow;
                cwmanager.StartOffset = ln.Offset + offset;
                return cwmanager;
            }
            public T BuildList<T>(TextBox control, Func<T> onDataExist)
                    where T : AutoCompleteWindow
            {
                var text = control.Text;
                int offset = 0;
                CheckRegex("^\\s*", text , (m) => offset += m.Length);
                var cwmanager = onDataExist();
                cwmanager.CompletionList.CompletionData = constantsTests;
                cwmanager.StartOffset = offset;
                return cwmanager;
            }

            #region properties -images-icons
            private ImageSource actionIcon;
            public ImageSource ActionIcon
            {
                get
                {
                    if (actionIcon != null) return actionIcon;
                    actionIcon = GetImageSource("action16.png");
                    return actionIcon;
                }
            }

            private ImageSource actionBaseIcon;
            public ImageSource ActionBaseIcon
            {
                get
                {
                    if (actionBaseIcon != null) return actionBaseIcon;
                    actionBaseIcon = GetImageSource("actionBase16.png");
                    return actionBaseIcon;
                }
            }

            private ImageSource testIcon;
            public ImageSource TestIcon
            {
                get
                {
                    if (testIcon != null) return testIcon;
                    testIcon = GetImageSource("testinfo16.png");
                    return testIcon;
                }
            }

            private ImageSource constIcon;
            public ImageSource ConstIcon
            {
                get
                {
                    if (constIcon != null) return constIcon;
                    constIcon = GetImageSource("const16.png");
                    return constIcon;
                }
            }

            #endregion
        }
}
